home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / program / 317 / asmsrc / expr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-10-20  |  30.0 KB  |  982 lines

  1. /* expr.c -operands, expressions- */
  2.  
  3. /* Copyright (C) 1987 Free Software Foundation, Inc.
  4.  
  5. This file is part of Gas, the GNU Assembler.
  6.  
  7. The GNU assembler is distributed in the hope that it will be
  8. useful, but WITHOUT ANY WARRANTY.  No author or distributor
  9. accepts responsibility to anyone for the consequences of using it
  10. or for whether it serves any particular purpose or works at all,
  11. unless he says so in writing.  Refer to the GNU Assembler General
  12. Public License for full details.
  13.  
  14. Everyone is granted permission to copy, modify and redistribute
  15. the GNU Assembler, but only under the conditions described in the
  16. GNU Assembler General Public License.  A copy of this license is
  17. supposed to have been given to you along with the GNU Assembler
  18. so you can know your rights and responsibilities.  It should be
  19. in a file named COPYING.  Among other things, the copyright
  20. notice and this notice must be preserved on all copies.  */
  21.  
  22. /*
  23.                 contents
  24. #includes & #defines
  25. _begin() & _end functions
  26. [internal] operand()
  27. [internal] clean_up_expression()
  28. [internal] expr_part()
  29. expr()
  30. get_symbol_end()
  31. */
  32.  
  33. /*
  34.  * This is really a branch office of as-read.c. I split it out to clearly
  35.  * distinguish the world of expressions from the world of statements.
  36.  * (It also gives smaller files to re-compile.)
  37.  * Here, "operand"s are of expressions, not instructions.
  38.  */
  39.  
  40. #include <ctype.h>
  41. #include "as.h"
  42. #include "flonum.h"
  43. #include "read.h"
  44. #include "struc-symbol.h"
  45. #include "expr.h"
  46. #include "obstack.h"
  47. #include "symbols.h"
  48.  
  49. void clean_up_expression();    /* Internal. */
  50. extern char EXP_CHARS[];    /* JF hide MD floating pt stuff all the same place */
  51. extern char FLT_CHARS[];
  52.  
  53. /*
  54.  * Build any floating-point literal here.
  55.  * Also build any bignum literal here.
  56.  */
  57.  
  58. LITTLENUM_TYPE    generic_buffer [6];    /* JF this is a hack */
  59. /* Seems atof_machine can backscan through generic_bignum and hit whatever
  60.    happens to be loaded before it in memory.  And its way too complicated
  61.    for me to fix right.  Thus a hack
  62.  */
  63. LITTLENUM_TYPE    generic_bignum [SIZE_OF_LARGE_NUMBER];
  64. FLONUM_TYPE    generic_floating_point_number =
  65. {
  66.   & generic_bignum [0],        /* low */
  67.   & generic_bignum [SIZE_OF_LARGE_NUMBER - 1], /* high */
  68.   0,                /* leader */
  69.   0,                /* exponent */
  70.   0                /* sign */
  71. };
  72.  
  73. /*
  74.  * Summary of operand().
  75.  *
  76.  * in:    Input_line_pointer points to 1st char of operand, which may
  77.  *    be a space.
  78.  *
  79.  * out:    A expressionS. X_seg determines how to understand the rest of the
  80.  *    expressionS.
  81.  *    The operand may have been empty: in this case X_seg == SEG_NONE.
  82.  *    Input_line_pointer -> (next non-blank) char after operand.
  83.  *
  84.  */
  85.  
  86. static segT
  87. operand (expressionP)
  88.      register expressionS *    expressionP;
  89. {
  90.   register char        c;
  91.   register char *name;    /* points to name of symbol */
  92.   register struct symbol *    symbolP; /* Points to symbol */
  93.  
  94.   extern  char hex_value[];    /* In hex_value.c */
  95.   char    *local_label_name();
  96.  
  97.   SKIP_WHITESPACE();        /* Leading whitespace is part of operand. */
  98.   c = * input_line_pointer ++;    /* Input_line_pointer -> past char in c. */
  99.   if (isdigit(c))
  100.     {
  101.       register valueT    number;    /* offset or (absolute) value */
  102.       register short int digit;    /* value of next digit in current radix */
  103.                 /* invented for humans only, hope */
  104.                 /* optimising compiler flushes it! */
  105.       register short int radix;    /* 8, 10 or 16 */
  106.                 /* 0 means we saw start of a floating- */
  107.                 /* point constant. */
  108.       register short int maxdig;/* Highest permitted digit value. */
  109.       register int    too_many_digits; /* If we see >= this number of */
  110.                 /* digits, assume it is a bignum. */
  111.       register char *    digit_2; /* -> 2nd digit of number. */
  112.                int    small;    /* TRUE if fits in 32 bits. */
  113.  
  114.       if (c=='0')
  115.     {            /* non-decimal radix */
  116.       if ((c = * input_line_pointer ++)=='x' || c=='X')
  117.         {
  118.           c = * input_line_pointer ++; /* read past "0x" or "0X" */
  119.           maxdig = radix = 16;
  120.           too_many_digits = 9;
  121.         }
  122.       else
  123.         {
  124.           /* If it says '0f' and the line ends or it DOESN'T look like
  125.              a floating point #, its a local label ref.  DTRT */
  126.           if(c=='f' && (! *input_line_pointer ||
  127.                 (!index("+-.0123456789",*input_line_pointer) &&
  128.                  !index(EXP_CHARS,*input_line_pointer))))
  129.         {
  130.               maxdig = radix = 10;
  131.           too_many_digits = 11;
  132.           c='0';
  133.           input_line_pointer-=2;
  134.         }
  135.           else if (c && index (FLT_CHARS,c))
  136.         {
  137.           radix = 0;    /* Start of floating-point constant. */
  138.                 /* input_line_pointer -> 1st char of number. */
  139.           expressionP -> X_add_number =  - (isupper(c) ? tolower(c) : c);
  140.         }
  141.           else
  142.         {        /* By elimination, assume octal radix. */
  143.           radix = 8;
  144.           maxdig = 10;    /* Un*x sux. Compatibility. */
  145.           too_many_digits = 11;
  146.         }
  147.         }
  148.       /* c == char after "0" or "0x" or "0X" or "0e" etc.*/
  149.     }
  150.       else
  151.     {
  152.       maxdig = radix = 10;
  153.       too_many_digits = 11;
  154.     }
  155.       if (radix)
  156.     {            /* Fixed-point integer constant. */
  157.                 /* May be bignum, or may fit in 32 bits. */
  158. /*
  159.  * Most numbers fit into 32 bits, and we want this case to be fast.
  160.  * So we pretend it will fit into 32 bits. If, after making up a 32
  161.  * bit number, we realise that we have scanned more digits than
  162.  * comfortably fit into 32 bits, we re-scan the digits coding
  163.  * them into a bignum. For decimal and octal numbers we are conservative: some
  164.  * numbers may be assumed bignums when in fact they do fit into 32 bits.
  165.  * Numbers of any radix can have excess leading zeros: we strive
  166.  * to recognise this and cast them back into 32 bits.
  167.  * We must check that the bignum really is more than 32
  168.  * bits, and change it back to a 32-bit number if it fits.
  169.  * The number we are looking for is expected to be positive, but
  170.  * if it fits into 32 bits as an unsigned number, we let it be a 32-bit
  171.  * number. The cavalier approach is for speed in ordinary cases.
  172.  */
  173.       digit_2 = input_line_pointer;
  174.       for (number=0;  (digit=hex_value[c])<maxdig;  c = * input_line_pointer ++)
  175.         {
  176.           number = number * radix + digit;
  177.         }
  178.       /* C contains character after number. */
  179.       /* Input_line_pointer -> char after C. */
  180.       small = input_line_pointer - digit_2 < too_many_digits;
  181.       if ( ! small)
  182.         {
  183.           /*
  184.            * We saw a lot of digits. Manufacture a bignum the hard way.
  185.            */
  186.           LITTLENUM_TYPE *    leader;    /* -> high order littlenum of the bignum. */
  187.           LITTLENUM_TYPE *    pointer; /* -> littlenum we are frobbing now. */
  188.           long int        carry;
  189.  
  190.           leader = generic_bignum;
  191.           generic_bignum [0] = 0;
  192.                 /* We could just use digit_2, but lets be mnemonic. */
  193.           input_line_pointer = -- digit_2; /* -> 1st digit. */
  194.           c = *input_line_pointer ++;
  195.           for (;   (carry = hex_value [c]) < maxdig;   c = * input_line_pointer ++)
  196.         {
  197.           for (pointer = generic_bignum;
  198.                pointer <= leader;
  199.                pointer ++)
  200.             {
  201.               long int    work;
  202.  
  203.               work = carry + radix * * pointer;
  204.               * pointer = work & LITTLENUM_MASK;
  205.               carry = work >> LITTLENUM_NUMBER_OF_BITS;
  206.             }
  207.           if (carry)
  208.             {
  209.               if (leader < generic_bignum + SIZE_OF_LARGE_NUMBER - 1)
  210.             {    /* Room to grow a longer bignum. */
  211.               * ++ leader = carry;
  212.             }
  213.             }
  214.         }
  215.           /* Again, C is char after number, */
  216.           /* input_line_pointer -> after C. */
  217.           know( BITS_PER_INT == 32 );
  218.           know( LITTLENUM_NUMBER_OF_BITS == 16 );
  219.           /* Hence the constant "2" in the next line. */
  220.           if (leader < generic_bignum + 2)
  221.         {        /* Will fit into 32 bits. */
  222.           number =
  223.             ( (generic_bignum [1] & LITTLENUM_MASK) << LITTLENUM_NUMBER_OF_BITS )
  224.             | (generic_bignum [0] & LITTLENUM_MASK);
  225.           small = TRUE;
  226.         }
  227.           else
  228.         {
  229.           number = leader - generic_bignum + 1;    /* Number of littlenums in the bignum. */
  230.         }
  231.         }
  232.       if (small)
  233.         {
  234.           /*
  235.            * Here with number, in correct radix. c is the next char.
  236.            * Note that unlike Un*x, we allow "011f" "0x9f" to
  237.            * both mean the same as the (conventional) "9f". This is simply easier
  238.            * than checking for strict canonical form. Syntax sux!
  239.            */
  240.           if (number<10)
  241.         {
  242.           if (c=='b')
  243.             {
  244.               /*
  245.                * Backward ref to local label.
  246.                * Because it is backward, expect it to be DEFINED.
  247.                */
  248.               /*
  249.                * Construct a local label.
  250.                */
  251.               name = local_label_name ((int)number, 0);
  252.               if ( (symbolP = symbol_table_lookup(name)) /* seen before */
  253.               && (symbolP -> sy_type & N_TYPE) != N_UNDF /* symbol is defined: OK */
  254.               )
  255.             {        /* Expected path: symbol defined. */
  256.               /* Local labels are never absolute. Don't waste time checking absoluteness. */
  257.               know(   (symbolP -> sy_type & N_TYPE) == N_DATA
  258.                    || (symbolP -> sy_type & N_TYPE) == N_TEXT );
  259.               expressionP -> X_add_symbol = symbolP;
  260.               expressionP -> X_add_number = 0;
  261.               expressionP -> X_seg          = N_TYPE_seg [symbolP -> sy_type];
  262.             }
  263.               else
  264.             {        /* Either not seen or not defined. */
  265.               as_warn( "Backw. ref to unknown label \"%d:\", 0 assumed.",
  266.                   number
  267.                   );
  268.               expressionP -> X_add_number = 0;
  269.               expressionP -> X_seg        = SEG_ABSOLUTE;
  270.             }
  271.             }
  272.           else
  273.             {
  274.               if (c=='f')
  275.             {
  276.               /*
  277.                * Forward reference. Expect symbol to be undefined or
  278.                * unknown. Undefined: seen it before. Unknown: never seen
  279.                * it in this pass.
  280.                * Construct a local label name, then an undefined symbol.
  281.                * Don't create a XSEG frag for it: caller may do that.
  282.                * Just return it as never seen before.
  283.                */
  284.               name = local_label_name ((int)number, 1);
  285.               if ( symbolP = symbol_table_lookup( name ))
  286.                 {
  287.                   /* We have no need to check symbol properties. */
  288.                   know(   (symbolP -> sy_type & N_TYPE) == N_UNDF
  289.                    || (symbolP -> sy_type & N_TYPE) == N_DATA
  290.                    || (symbolP -> sy_type & N_TYPE) == N_TEXT);
  291.                 }
  292.               else
  293.                 {
  294.                   symbolP = symbol_new (name, N_UNDF, 0,0,0, & zero_address_frag);
  295.                   symbol_table_insert (symbolP);
  296.                 }
  297.               expressionP -> X_add_symbol      = symbolP;
  298.               expressionP -> X_seg             = SEG_UNKNOWN;
  299.               expressionP -> X_subtract_symbol = NULL;
  300.               expressionP -> X_add_number      = 0;
  301.             }
  302.               else
  303.             {        /* Really a number, not a local label. */
  304.               expressionP -> X_add_number = number;
  305.               expressionP -> X_seg        = SEG_ABSOLUTE;
  306.               input_line_pointer --; /* Restore following character. */
  307.             }        /* if (c=='f') */
  308.             }            /* if (c=='b') */
  309.         }
  310.           else
  311.         {            /* Really a number. */
  312.           expressionP -> X_add_number = number;
  313.           expressionP -> X_seg        = SEG_ABSOLUTE;
  314.           input_line_pointer --; /* Restore following character. */
  315.         }            /* if (number<10) */
  316.         }
  317.       else
  318.         {
  319.           expressionP -> X_add_number = number;
  320.           expressionP -> X_seg = SEG_BIG;
  321.           input_line_pointer --; /* -> char following number. */
  322.         }            /* if (small) */
  323.     }            /* (If integer constant) */
  324.       else
  325.     {            /* input_line_pointer -> */
  326.                 /* floating-point constant. */
  327.       int error_code;
  328.  
  329.       error_code = atof_generic
  330.         (& input_line_pointer, ".", EXP_CHARS,
  331.          & generic_floating_point_number);
  332.  
  333.       if (error_code)
  334.         {
  335.           if (error_code == ERROR_EXPONENT_OVERFLOW)
  336.         {
  337.           as_warn( "Bad floating-point constant: exponent overflow, probably assembling junk" );
  338.         }
  339.           else
  340.         {          
  341.           as_warn( "Bad floating-point constant: unknown error code=%d.", error_code);
  342.         }
  343.         }
  344.       expressionP -> X_seg = SEG_BIG;
  345.                 /* input_line_pointer -> just after constant, */
  346.                 /* which may point to whitespace. */
  347.       know( expressionP -> X_add_number < 0 ); /* < 0 means "floating point". */
  348.     }            /* if (not floating-point constant) */
  349.     }
  350.   else
  351.     {                /* here if did not begin with a digit */
  352.       if ( is_name_beginner(c) )
  353.     {
  354.       /*
  355.        * Identifier begins here.
  356.        * This is kludged for speed, so code is repeated.
  357.        */
  358.       name =  -- input_line_pointer;
  359.       c = get_symbol_end();
  360.       symbolP = symbol_table_lookup(name);
  361.       if (symbolP)
  362.         {
  363.           /*
  364.            * If we have an absolute symbol, then we know it's value now.
  365.            */
  366.           register segT        seg;
  367.  
  368.           seg = N_TYPE_seg [(int) symbolP -> sy_type & N_TYPE];
  369.           if ((expressionP -> X_seg = seg) == SEG_ABSOLUTE )
  370.         {
  371.           expressionP -> X_add_number = symbolP -> sy_value;
  372.         }
  373.           else
  374.         {
  375.           expressionP -> X_add_number  = 0;
  376.           expressionP -> X_add_symbol  = symbolP;
  377.         }
  378.         }
  379.       else
  380.         {
  381.           expressionP -> X_add_symbol
  382.         = symbolP
  383.           = symbol_new (name, N_UNDF, 0,0,0, & zero_address_frag);
  384.  
  385.           expressionP -> X_add_number  = 0;
  386.           expressionP -> X_seg         = SEG_UNKNOWN;
  387.           symbol_table_insert (symbolP);
  388.         }
  389.       * input_line_pointer = c;
  390.       expressionP -> X_subtract_symbol = NULL;
  391.     }
  392.       else
  393.     {            /* didn't begin with digit & not a name */
  394.       if (c=='(')
  395.         {
  396.           (void)expression( expressionP );
  397.           /* Expression() will pass trailing whitespace */
  398.           if ( * input_line_pointer ++ != ')' )
  399.         {
  400.           as_warn( "Missing ')' assumed");
  401.           input_line_pointer --;
  402.         }
  403.           /* here with input_line_pointer -> char after "(...)" */
  404.         }
  405.       else
  406.         {
  407.           if ( c=='~' || c=='-' )
  408.         {        /* unary operator: hope for SEG_ABSOLUTE */
  409.           switch(operand (expressionP)) {
  410.           case SEG_ABSOLUTE:
  411.             /* input_line_pointer -> char after operand */
  412.               if ( c=='-' )
  413.             {
  414.               expressionP -> X_add_number = - expressionP -> X_add_number;
  415. /*
  416.  * Notice: '-' may  overflow: no warning is given. This is compatible
  417.  * with other people's assemblers. Sigh.
  418.  */
  419.             }
  420.               else
  421.             {
  422.               expressionP -> X_add_number = ~ expressionP -> X_add_number;
  423.             }
  424.               break;
  425.  
  426.           case SEG_TEXT:
  427.           case SEG_DATA:
  428.           case SEG_BSS:
  429.           case SEG_PASS1:
  430.           case SEG_UNKNOWN:
  431.             if(c=='-') {        /* JF I hope this hack works */
  432.                 expressionP->X_subtract_symbol=expressionP->X_add_symbol;
  433.             expressionP->X_add_symbol=0;
  434.             expressionP->X_seg=SEG_DIFFERENCE;
  435.             break;
  436.             }
  437.           default:        /* unary on non-absolute is unsuported */
  438.               as_warn("Unary operator %c ignored because bad operand follows", c);
  439.               break;
  440.               /* Expression undisturbed from operand(). */
  441.             }
  442.         }
  443.           else
  444.         {
  445.           if (c=='\'')
  446.             {
  447. /*
  448.  * Warning: to conform to other people's assemblers NO ESCAPEMENT is permitted
  449.  * for a single quote. The next character, parity errors and all, is taken
  450.  * as the value of the operand. VERY KINKY.
  451.  */
  452.               expressionP -> X_add_number = * input_line_pointer ++;
  453.               expressionP -> X_seg        = SEG_ABSOLUTE;
  454.             }
  455.           else
  456.             {
  457.               /* can't imagine any other kind of operand */
  458.               expressionP -> X_seg = SEG_NONE;
  459.               input_line_pointer --;
  460.             }
  461.         }
  462.         }
  463.     }
  464.     }
  465. /*
  466.  * It is more 'efficient' to clean up the expressions when they are created.
  467.  * Doing it here saves lines of code.
  468.  */
  469.   clean_up_expression (expressionP);
  470.   SKIP_WHITESPACE();        /* -> 1st char after operand. */
  471.   know( * input_line_pointer != ' ' );
  472.   return (expressionP -> X_seg);
  473. }                /* operand */
  474.  
  475. /* Internal. Simplify a struct expression for use by expr() */
  476.  
  477. /*
  478.  * In:    address of a expressionS.
  479.  *    The X_seg field of the expressionS may only take certain values.
  480.  *    Now, we permit SEG_PASS1 to make code smaller & faster.
  481.  *    Elsewise we waste time special-case testing. Sigh. Ditto SEG_NONE.
  482.  * Out:    expressionS may have been modified:
  483.  *    'foo-foo' symbol references cancelled to 0,
  484.  *        which changes X_seg from SEG_DIFFERENCE to SEG_ABSOLUTE;
  485.  *    Unused fields zeroed to help expr().
  486.  */
  487.  
  488. static void
  489. clean_up_expression (expressionP)
  490.      register expressionS * expressionP;
  491. {
  492.   switch (expressionP -> X_seg)
  493.     {
  494.     case SEG_NONE:
  495.     case SEG_PASS1:
  496.       expressionP -> X_add_symbol    = NULL;
  497.       expressionP -> X_subtract_symbol    = NULL;
  498.       expressionP -> X_add_number    = 0;
  499.       break;
  500.  
  501.     case SEG_BIG:
  502.     case SEG_ABSOLUTE:
  503.       expressionP -> X_subtract_symbol    = NULL;
  504.       expressionP -> X_add_symbol    = NULL;
  505.       break;
  506.  
  507.     case SEG_TEXT:
  508.     case SEG_DATA:
  509.     case SEG_BSS:
  510.     case SEG_UNKNOWN:
  511.       expressionP -> X_subtract_symbol    = NULL;
  512.       break;
  513.  
  514.     case SEG_DIFFERENCE:
  515.       /*
  516.        * It does not hurt to 'cancel' NULL==NULL
  517.        * when comparing symbols for 'eq'ness.
  518.        * It is faster to re-cancel them to NULL
  519.        * than to check for this special case.
  520.        */
  521.       if (expressionP -> X_subtract_symbol == expressionP -> X_add_symbol)
  522.     {
  523.       expressionP -> X_subtract_symbol    = NULL;
  524.       expressionP -> X_add_symbol        = NULL;
  525.       expressionP -> X_seg            = SEG_ABSOLUTE;
  526.     }
  527.       break;
  528.  
  529.     default:
  530.       BAD_CASE( expressionP -> X_seg);
  531.       break;
  532.     }
  533. }
  534.  
  535. /*
  536.  *            expr_part ()
  537.  *
  538.  * Internal. Made a function because this code is used in 2 places.
  539.  * Generate error or correct X_?????_symbol of expressionS.
  540.  */
  541.  
  542. /*
  543.  * symbol_1 += symbol_2 ... well ... sort of.
  544.  */
  545.  
  546. static segT
  547. expr_part (symbol_1_PP, symbol_2_P)
  548.      struct symbol **    symbol_1_PP;
  549.      struct symbol *    symbol_2_P;
  550. {
  551.   segT            return_value;
  552.  
  553.   know(    (* symbol_1_PP)                   == NULL
  554.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_TEXT
  555.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_DATA
  556.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_BSS
  557.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF
  558.        );
  559.   know(      symbol_2_P             == NULL
  560.        ||    (symbol_2_P   -> sy_type & N_TYPE) == N_TEXT
  561.        ||    (symbol_2_P   -> sy_type & N_TYPE) == N_DATA
  562.        ||    (symbol_2_P   -> sy_type & N_TYPE) == N_BSS
  563.        ||    (symbol_2_P   -> sy_type & N_TYPE) == N_UNDF
  564.        );
  565.   if (* symbol_1_PP)
  566.     {
  567.       if (((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF)
  568.     {
  569.       if (symbol_2_P)
  570.         {
  571.           return_value = SEG_PASS1;
  572.           * symbol_1_PP = NULL;
  573.         }
  574.       else
  575.         {
  576.           know( ((* symbol_1_PP) -> sy_type & N_TYPE) == N_UNDF)
  577.           return_value = SEG_UNKNOWN;
  578.         }
  579.     }
  580.       else
  581.     {
  582.       if (symbol_2_P)
  583.         {
  584.           if ((symbol_2_P -> sy_type & N_TYPE) == N_UNDF)
  585.         {
  586.           * symbol_1_PP = NULL;
  587.           return_value = SEG_PASS1;
  588.         }
  589.           else
  590.         {
  591.           /* {seg1} - {seg2} */
  592.           as_warn( "Expression too complex, 2 symbols forgotten: \"%s\" \"%s\"",
  593.               (* symbol_1_PP) -> sy_name, symbol_2_P -> sy_name );
  594.           * symbol_1_PP = NULL;
  595.           return_value = SEG_ABSOLUTE;
  596.         }
  597.         }
  598.       else
  599.         {
  600.           return_value = N_TYPE_seg [(* symbol_1_PP) -> sy_type & N_TYPE];
  601.         }
  602.     }
  603.     }
  604.   else
  605.     {                /* (* symbol_1_PP) == NULL */
  606.       if (symbol_2_P)
  607.     {
  608.       * symbol_1_PP = symbol_2_P;
  609.       return_value = N_TYPE_seg [(symbol_2_P) -> sy_type & N_TYPE];
  610.     }
  611.       else
  612.     {
  613.       * symbol_1_PP = NULL;
  614.       return_value = SEG_ABSOLUTE;
  615.     }
  616.     }
  617.   know(   return_value == SEG_ABSOLUTE            
  618.        || return_value == SEG_TEXT            
  619.        || return_value == SEG_DATA            
  620.        || return_value == SEG_BSS            
  621.        || return_value == SEG_UNKNOWN            
  622.        || return_value == SEG_PASS1            
  623.        );
  624.   know(   (* symbol_1_PP) == NULL                
  625.        || ((* symbol_1_PP) -> sy_type & N_TYPE) == seg_N_TYPE [(int) return_value] );
  626.   return (return_value);
  627. }                /* expr_part() */
  628.  
  629. /* Expression parser. */
  630.  
  631. /*
  632.  * We allow an empty expression, and just assume (absolute,0) silently.
  633.  * Unary operators and parenthetical expressions are treated as operands.
  634.  * As usual, Q==quantity==operand, O==operator, X==expression mnemonics.
  635.  *
  636.  * We used to do a aho/ullman shift-reduce parser, but the logic got so
  637.  * warped that I flushed it and wrote a recursive-descent parser instead.
  638.  * Now things are stable, would anybody like to write a fast parser?
  639.  * Most expressions are either register (which does not even reach here)
  640.  * or 1 symbol. Then "symbol+constant" and "symbol-symbol" are common.
  641.  * So I guess it doesn't really matter how inefficient more complex expressions
  642.  * are parsed.
  643.  *
  644.  * After expr(RANK,resultP) input_line_pointer -> operator of rank <= RANK.
  645.  * Also, we have consumed any leading or trailing spaces (operand does that)
  646.  * and done all intervening operators.
  647.  */
  648.  
  649. typedef enum
  650. {
  651. O_illegal,            /* (0)  what we get for illegal op */
  652.  
  653. O_multiply,            /* (1)  * */
  654. O_divide,            /* (2)  / */
  655. O_modulus,            /* (3)  % */
  656. O_left_shift,            /* (4)  < */
  657. O_right_shift,            /* (5)  > */
  658. O_bit_inclusive_or,        /* (6)  | */
  659. O_bit_or_not,            /* (7)  ! */
  660. O_bit_exclusive_or,        /* (8)  ^ */
  661. O_bit_and,            /* (9)  & */
  662. O_add,                /* (10) + */
  663. O_subtract            /* (11) - */
  664. }
  665. operatorT;
  666.  
  667. #define __ O_illegal
  668.  
  669. static operatorT op_encoding [256] = {    /* maps ASCII -> operators */
  670.  
  671. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  672. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  673.  
  674. __, O_bit_or_not, __, __, __, O_modulus, O_bit_and, __,
  675. __, __, O_multiply, O_add, __, O_subtract, __, O_divide,
  676. __, __, __, __, __, __, __, __,
  677. __, __, __, __, O_left_shift, __, O_right_shift, __,
  678. __, __, __, __, __, __, __, __,
  679. __, __, __, __, __, __, __, __,
  680. __, __, __, __, __, __, __, __,
  681. __, __, __, __, __, __, O_bit_exclusive_or, __,
  682. __, __, __, __, __, __, __, __,
  683. __, __, __, __, __, __, __, __,
  684. __, __, __, __, __, __, __, __,
  685. __, __, __, __, O_bit_inclusive_or, __, __, __,
  686.  
  687. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  688. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  689. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  690. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  691. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  692. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  693. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
  694. __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __
  695. };
  696.  
  697.  
  698. /*
  699.  *    Rank    Examples
  700.  *    0    operand, (expression)
  701.  *    1    + -
  702.  *    2    & ^ ! |
  703.  *    3    * / % < >
  704.  */
  705. typedef char operator_rankT;
  706. static operator_rankT
  707. op_rank [] = { 0, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1 };
  708.  
  709. segT                /* Return resultP -> X_seg. */
  710. expr (rank, resultP)
  711.      register operator_rankT    rank; /* Larger # is higher rank. */
  712.      register expressionS *    resultP; /* Deliver result here. */
  713. {
  714.   expressionS        right;
  715.   register operatorT    op_left;
  716.   register char        c_left;    /* 1st operator character. */
  717.   register operatorT    op_right;
  718.   register char        c_right;
  719.  
  720.   know( rank >= 0 );
  721.   (void)operand (resultP);
  722.   know( * input_line_pointer != ' ' ); /* Operand() gobbles spaces. */
  723.   c_left = * input_line_pointer; /* Potential operator character. */
  724.   op_left = op_encoding [c_left];
  725.   while (op_left != O_illegal && op_rank [(int) op_left] > rank)
  726.     {
  727.       input_line_pointer ++;    /* -> after 1st character of operator. */
  728.                 /* Operators "<<" and ">>" have 2 characters. */
  729.       if (* input_line_pointer == c_left && (c_left == '<' || c_left == '>') )
  730.     {
  731.       input_line_pointer ++;
  732.     }            /* -> after operator. */
  733.       if (SEG_NONE == expr (op_rank[(int) op_left], &right))
  734.     {
  735.       as_warn("Missing operand value assumed absolute 0.");
  736.       resultP -> X_add_number    = 0;
  737.       resultP -> X_subtract_symbol    = NULL;
  738.       resultP -> X_add_symbol    = NULL;
  739.       resultP -> X_seg = SEG_ABSOLUTE;
  740.     }
  741.       know( * input_line_pointer != ' ' );
  742.       c_right = * input_line_pointer;
  743.       op_right = op_encoding [c_right];
  744.       if (* input_line_pointer == c_right && (c_right == '<' || c_right == '>') )
  745.     {
  746.       input_line_pointer ++;
  747.     }            /* -> after operator. */
  748.       know(   (int) op_right == 0
  749.        || op_rank [(int) op_right] <= op_rank[(int) op_left] );
  750.       /* input_line_pointer -> after right-hand quantity. */
  751.       /* left-hand quantity in resultP */
  752.       /* right-hand quantity in right. */
  753.       /* operator in op_left. */
  754.       if ( resultP -> X_seg == SEG_PASS1 || right . X_seg == SEG_PASS1 )
  755.     {
  756.       resultP -> X_seg = SEG_PASS1;
  757.     }
  758.       else
  759.     {
  760.       if ( resultP -> X_seg == SEG_BIG )
  761.         {
  762.           as_warn( "Left operand of %c is a %s.  Integer 0 assumed.",
  763.               c_left, resultP -> X_add_number > 0 ? "bignum" : "float");
  764.           resultP -> X_seg = SEG_ABSOLUTE;
  765.           resultP -> X_add_symbol = 0;
  766.           resultP -> X_subtract_symbol = 0;
  767.           resultP -> X_add_number = 0;
  768.         }
  769.       if ( right . X_seg == SEG_BIG )
  770.         {
  771.           as_warn( "Right operand of %c is a %s.  Integer 0 assumed.",
  772.               c_left, right . X_add_number > 0 ? "bignum" : "float");
  773.           right . X_seg = SEG_ABSOLUTE;
  774.           right . X_add_symbol = 0;
  775.           right . X_subtract_symbol = 0;
  776.           right . X_add_number = 0;
  777.         }
  778.       if ( op_left == O_subtract )
  779.         {
  780.           /*
  781.            * Convert - into + by exchanging symbols and negating number.
  782.            * I know -infinity can't be negated in 2's complement:
  783.            * but then it can't be subtracted either. This trick
  784.            * does not cause any further inaccuracy.
  785.            */
  786.  
  787.           register struct symbol *    symbolP;
  788.  
  789.           right . X_add_number      = - right . X_add_number;
  790.           symbolP                   = right . X_add_symbol;
  791.           right . X_add_symbol    = right . X_subtract_symbol;
  792.           right . X_subtract_symbol = symbolP;
  793.           if (symbolP)
  794.         {
  795.           right . X_seg        = SEG_DIFFERENCE;
  796.         }
  797.           op_left = O_add;
  798.         }
  799.  
  800.       if ( op_left == O_add )
  801.         {
  802.           segT    seg1;
  803.           segT    seg2;
  804.           
  805.           know(   resultP -> X_seg == SEG_DATA        
  806.            || resultP -> X_seg == SEG_TEXT        
  807.            || resultP -> X_seg == SEG_BSS        
  808.            || resultP -> X_seg == SEG_UNKNOWN        
  809.            || resultP -> X_seg == SEG_DIFFERENCE    
  810.            || resultP -> X_seg == SEG_ABSOLUTE        
  811.            || resultP -> X_seg == SEG_PASS1        
  812.            );
  813.           know(     right .  X_seg == SEG_DATA        
  814.            ||   right .  X_seg == SEG_TEXT        
  815.            ||   right .  X_seg == SEG_BSS        
  816.            ||   right .  X_seg == SEG_UNKNOWN        
  817.            ||   right .  X_seg == SEG_DIFFERENCE    
  818.            ||   right .  X_seg == SEG_ABSOLUTE        
  819.            ||   right .  X_seg == SEG_PASS1        
  820.            );
  821.           
  822.           clean_up_expression (& right);
  823.           clean_up_expression (resultP);
  824.  
  825.           seg1 = expr_part (& resultP -> X_add_symbol, right . X_add_symbol);
  826.           seg2 = expr_part (& resultP -> X_subtract_symbol, right . X_subtract_symbol);
  827.           if (   seg1 == SEG_PASS1
  828.           || seg2 == SEG_PASS1)
  829.         {
  830.           need_pass_2 = TRUE;
  831.           resultP -> X_seg = SEG_PASS1;
  832.         }
  833.           else
  834.         {
  835.           if (seg2 == SEG_ABSOLUTE)
  836.             {
  837.               resultP -> X_seg = seg1;
  838.             }
  839.           else
  840.             {
  841.               know( seg2 != SEG_ABSOLUTE );
  842.               know( resultP -> X_subtract_symbol );
  843.               if (   seg1 != SEG_UNKNOWN
  844.               && seg1 != SEG_ABSOLUTE
  845.               && seg2 != SEG_UNKNOWN
  846.               && seg1 != seg2)
  847.             {
  848.               know( seg1 == SEG_TEXT || seg1 == SEG_DATA || seg1== SEG_BSS );
  849.               know( seg2 == SEG_TEXT || seg2 == SEG_DATA || seg2== SEG_BSS );
  850.               know( resultP -> X_add_symbol      );
  851.               know( resultP -> X_subtract_symbol );
  852.               as_warn("Expression too complex: forgetting %s - %s",
  853.                   resultP -> X_add_symbol      -> sy_name,
  854.                   resultP -> X_subtract_symbol -> sy_name);
  855.               resultP -> X_seg = SEG_ABSOLUTE;
  856.               /* Clean_up_expression() will do the rest. */
  857.             }
  858.               else
  859.             {
  860.               resultP -> X_seg = SEG_DIFFERENCE;
  861.             }    /* If relocation too complex. */
  862.             }        /* If seg2 == SEG_ABSOLUTE. */
  863.         }        /* If need pass 2. */
  864.           resultP -> X_add_number += right . X_add_number;
  865.           clean_up_expression (resultP);
  866.         }
  867.       else
  868.         {            /* Not +. */
  869.           if ( resultP -> X_seg == SEG_UNKNOWN || right . X_seg == SEG_UNKNOWN )
  870.         {
  871.           resultP -> X_seg = SEG_PASS1;
  872.           need_pass_2 = TRUE;
  873.         }
  874.           else
  875.         {
  876.           resultP -> X_subtract_symbol = NULL;
  877.           resultP -> X_add_symbol = NULL;
  878.           /* Will be SEG_ABSOLUTE. */
  879.           if ( resultP -> X_seg != SEG_ABSOLUTE || right . X_seg != SEG_ABSOLUTE )
  880.             {
  881.               as_warn( "Relocation error. Absolute 0 assumed.");
  882.               resultP -> X_seg        = SEG_ABSOLUTE;
  883.               resultP -> X_add_number = 0;
  884.             }
  885.           else
  886.             {
  887.               switch ( op_left )
  888.             {
  889.             case O_bit_inclusive_or:
  890.               resultP -> X_add_number |= right . X_add_number;
  891.               break;
  892.               
  893.             case O_modulus:
  894.               if (right . X_add_number)
  895.                 {
  896.                   resultP -> X_add_number %= right . X_add_number;
  897.                 }
  898.               else
  899.                 {
  900.                   as_warn( "Division by 0. 0 assumed." );
  901.                   resultP -> X_add_number = 0;
  902.                 }
  903.               break;
  904.               
  905.             case O_bit_and:
  906.               resultP -> X_add_number &= right . X_add_number;
  907.               break;
  908.               
  909.             case O_multiply:
  910.               resultP -> X_add_number *= right . X_add_number;
  911.               break;
  912.               
  913.             case O_divide:
  914.               if (right . X_add_number)
  915.                 {
  916.                   resultP -> X_add_number /= right . X_add_number;
  917.                 }
  918.               else
  919.                 {
  920.                   as_warn( "Division by 0. 0 assumed." );
  921.                   resultP -> X_add_number = 0;
  922.                 }
  923.               break;
  924.               
  925.             case O_left_shift:
  926.               resultP -> X_add_number <<= right . X_add_number;
  927.               break;
  928.               
  929.             case O_right_shift:
  930.               resultP -> X_add_number >>= right . X_add_number;
  931.               break;
  932.               
  933.             case O_bit_exclusive_or:
  934.               resultP -> X_add_number ^= right . X_add_number;
  935.               break;
  936.               
  937.             case O_bit_or_not:
  938.               resultP -> X_add_number |= ~ right . X_add_number;
  939.               break;
  940.               
  941.             default:
  942.               BAD_CASE( op_left );
  943.               break;
  944.             } /* switch(operator) */
  945.             }
  946.         }        /* If we have to force need_pass_2. */
  947.         }            /* If operator was +. */
  948.     }            /* If we didn't set need_pass_2. */
  949.       op_left = op_right;
  950.     }                /* While next operator is >= this rank. */
  951.   return (resultP -> X_seg);
  952. }
  953.  
  954. /*
  955.  *            get_symbol_end()
  956.  *
  957.  * This lives here because it belongs equally in expr.c & read.c.
  958.  * Expr.c is just a branch office read.c anyway, and putting it
  959.  * here lessens the crowd at read.c.
  960.  *
  961.  * Assume input_line_pointer is at start of symbol name.
  962.  * Advance input_line_pointer past symbol name.
  963.  * Turn that character into a '\0', returning its former value.
  964.  * This allows a string compare (RMS wants symbol names to be strings)
  965.  * of the symbol name.
  966.  * There will always be a char following symbol name, because all good
  967.  * lines end in end-of-line.
  968.  */
  969. char
  970. get_symbol_end()
  971. {
  972.   register char c;
  973.  
  974.   while ( is_part_of_name( c = * input_line_pointer ++ ) )
  975.     {
  976.     }
  977.   * -- input_line_pointer = 0;
  978.   return (c);
  979. }
  980.  
  981. /* end: expr.c */
  982.